//
// Copyright (C) [2024] Xingyun Integrated Circuit, Inc.
//
// GreenCode was a private technology asset of Xingyun Integrated Circuit， Inc （Confidential）
//  Author: Shawn.Tan
//  Date : 2025.10.28
//
//  History : Initial Version 2025.10.28
//

//
#include "VmInfoGPGPU.h"

#include <sstream>

#include "Generator.h"
#include "Log.h"
#include "Register.h"

using namespace std;

/*!
  \file VmInfoGPGPU.cc
  \brief GPGPU specific VM lookup info code.
*/

namespace Green {

  EVmRegimeType VmInfoGPGPU::RegimeType(bool* pIsValid) const
  {
    if (nullptr != pIsValid) {
      *pIsValid = true;
    }

    if (mPrivilegeLevelType == EPrivilegeLevelType::M)
    {
      return EVmRegimeType::M;
    }
    else if (mPrivilegeLevelType == EPrivilegeLevelType::S || mPrivilegeLevelType == EPrivilegeLevelType::U)
    {
      return EVmRegimeType::S;
    }
    /*else if (mPrivilegeLevelType == EPrivilegeLevelType::U)
    {
      return EVmRegimeType::U;
    }*/

    return EVmRegimeType::M;
  }

  const string VmInfoGPGPU::ToString() const
  {
    stringstream out_str;

    out_str << "PrivilegeLevel="  << EPrivilegeLevelType_to_string(mPrivilegeLevelType)
            << " MODE=" << BoolAttribute(EVmInfoBoolType::MODE)
            << " MPRV=" << BoolAttribute(EVmInfoBoolType::MPRV)
            << " TVM=" << BoolAttribute(EVmInfoBoolType::TVM);
            //<< " MPP=" << BoolAttribute(EVmInfoBoolType::MPP);

    return out_str.str();
  }

  void VmInfoGPGPU::GetCurrentStates(const Generator& rGen)
  {
    SetPrivilegeLevel(rGen.PrivilegeLevel());
    auto reg_file = rGen.GetRegisterFile();
    auto satp_reg = reg_file->RegisterLookup("satp");
    GetRegisterFieldState(satp_reg, EVmInfoBoolType::MODE);

    auto mstatus_reg = reg_file->RegisterLookup("mstatus");
    GetRegisterFieldState(mstatus_reg, EVmInfoBoolType::MPRV);
    GetRegisterFieldState(mstatus_reg, EVmInfoBoolType::TVM); //Trap Virtual Memory - if paging enable will cause exceptions on all vm ops
    //need MPP to determine paging enabled for priv=m MPRV=1 MPP=S
    //this can create a new unique case where instr's are direct mapped and data accesses are translated via 'S' addr translation and protection
  }

  const string VmInfoGPGPU::GetRegisterNameForField(EVmInfoBoolType attrType, const Generator& rGen) const
  {
    switch (attrType)
    {
      case EVmInfoBoolType::MODE:
        return "satp";
      case EVmInfoBoolType::MPRV:
      case EVmInfoBoolType::TVM:
        return "mstatus";
      default:
        LOG(fail) << "{VmInfoGPGPU::GetRegisterNameForField} Unsupported bool attr enum value: " << EVmInfoBoolType_to_string(attrType) << endl;
        FAIL("invalid_attr_type");
    }
    return "";
  }

  bool VmInfoGPGPU::PagingEnabled() const
  {
    if (BoolAttribute(EVmInfoBoolType::MODE) &&
        (mPrivilegeLevelType == EPrivilegeLevelType::S || mPrivilegeLevelType == EPrivilegeLevelType::U))
    {
      return true;
    }

    //if (mPrivilegeLevelType == EPrivilegeLevelType::M && BoolAttribute(EVmInfoBoolType::MPRV) && MPP == EPrivilegeLevelType::S)
    //  data accesses are paging enabled/instructions are not

    return false;
  }

}
